package com.qls.ali.biz.order.service.biz.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.qls.ali.biz.order.entity.*;
import com.qls.ali.biz.order.service.biz.ReceOrderService;
import com.qls.ali.biz.order.service.mybatis.*;
import com.qls.ali.biz.order.util.GeneValidateResponse;
import com.qls.ali.biz.order.util.OrderConstant;
import com.qls.ali.biz.order.util.PriceUtil;
import com.qls.ali.biz.order.util.XmlUtils;
import com.qls.core.ali.order.bookrq.request.BookRq;
import com.qls.core.ali.order.bookrq.request.OrderGuest;
import com.qls.core.ali.order.bookrq.response.BookRqResult;
import com.qls.core.ali.order.cancelrq.CancelRq;
import com.qls.core.ali.order.cancelrq.CancelRqResult;
import com.qls.core.ali.order.common.AuthenticationToken;
import com.qls.core.ali.order.common.DailyInfo;
import com.qls.core.ali.order.orderrefundrq.request.OrderRefundRq;
import com.qls.core.ali.order.paysuccessrq.request.PaySuccess;
import com.qls.core.ali.order.paysuccessrq.response.PaySuccessResult;
import com.qls.core.ali.order.querystatusrq.request.QueryStatusRqRequest;
import com.qls.core.ali.order.querystatusrq.response.QueryStatusRqResult;
import com.qls.core.ali.order.validaterq.request.ValidateRq;
import com.qls.core.constant.Constant;
import com.qls.core.dto.HtDailyRoom;
import com.qls.core.dto.PushRatesBody;
import com.qls.core.entity.DtStore;
import com.qls.core.entity.OpOurRateplanPrice;
import com.qls.core.utils.DateUtils;
import com.qls.core.utils.R;
import com.qls.mt.api.MtRemoteService;
import com.qls.rabbitmq.SendMsg;
import com.qls.redis.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author doyoung
 */
@Service
@Slf4j
public class ReceOrderServiceImpl implements ReceOrderService {

    @Autowired
    private OrderService orderService;

    @Autowired
    private DailyInfoService dailyInfoService;

    @Autowired
    private DailyOriInfoService dailyOriInfoService;

    @Autowired
    private DailyDisInfoService dailyDisInfoService;

    @Autowired
    private GuestService guestService;

    @Autowired
    private OpGroupService opGroupService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private SendMsg sendMsg;

    @Autowired
    private MtRemoteService mtRemoteService;

    @Autowired
    private DtStoreService dtStoreService;

    /**
     * 下单前校验
     *
     * @param xml String
     * @return String
     */
    @Override
    public String validate(String xml) {
        ValidateRq validateRq = XmlUtils.fromXml(xml, ValidateRq.class);
        if (Objects.isNull(validateRq)) {
            log.warn("飞猪报文解析失败：{}", xml);
            return XmlUtils.toXml(GeneValidateResponse.gene(false, null, "2"));
        }
        String[] strings = validateRq.getRatePlanCode().split("qls");
        List<HtDailyRoom> dailyRooms = redisUtil.getRatesBatch(DateUtils.getBetweenDays(validateRq.getCheckIn(), validateRq.getCheckOut()), strings[0]);
        if (dailyRooms.isEmpty()) {
            log.warn("店铺：{}，携程下单前校验，验单失败，酒店id：{}，RP：{}，缓存价格日历缺失",
                    validateRq.getAuthenticationToken().getUsername(), validateRq.getHotelId(), strings[0]);
            return XmlUtils.toXml(GeneValidateResponse.gene(false, null, "-1"));
        }
        List<DailyInfo> dailyInfos = new ArrayList<>();
        for (HtDailyRoom dailyroomEntity : dailyRooms) {
            String date = dailyroomEntity.getDate();
            Integer price = dailyroomEntity.getPrice();
            DailyInfo dailyInfo = new DailyInfo();
            dailyInfo.setDay(date);
            dailyInfo.setPrice(price);
            dailyInfo.setSubPrice(dailyroomEntity.getSubPrice());
            dailyInfos.add(dailyInfo);
        }
        validateRq.setDailyInfos(dailyInfos);
        validateRq.setRatePlanCode(strings[0]);
        // 掉用验单接口
        R r = mtRemoteService.validate(validateRq);
        int code = r.getCode();
        if (code == 0) {
            List<HtDailyRoom> htDailyRooms = new ArrayList<>();
            List<Object> objects = (List<Object>) r.get("data");
            for (Object object : objects) {
                String jsonObject = JSON.toJSONString(object);
                //将json转成需要的对象
                HtDailyRoom htDailyRoom = JSONObject.parseObject(jsonObject, HtDailyRoom.class);
                htDailyRooms.add(htDailyRoom);
            }
            // todo 价格比较 佣金比较 返回值为0 价格佣金没问题 1 佣金变化 2价格变化
            int flag = this.isUpdate(htDailyRooms, dailyRooms);
            // 佣金变化 或者价格变化
            if (flag != 0) {
                this.cacheAndPush(htDailyRooms, validateRq.getCheckIn(), validateRq.getCheckOut(), strings[0], flag);
            }
            List<DailyInfo> dailyInfosList = validateRq.getDailyInfos();
            List<OpOurRateplanPrice> ourRateplanPrices = (List<OpOurRateplanPrice>) redisUtil.hashGet(Constant.Redis.CRPID_USE_CPRICE.getValue(), strings[1]);
            if (ourRateplanPrices.isEmpty()) {
                log.warn("店铺：{}，美团下单前校验，验单失败，酒店id：{}，RP：{}，自定义价格计划缺失阶梯加幅",
                        validateRq.getAuthenticationToken().getUsername(), validateRq.getHotelId(), strings[0]);
                return XmlUtils.toXml(GeneValidateResponse.gene(false, null, "-1"));
            }
            for (DailyInfo dailyInfo : dailyInfosList) {
                dailyInfo.setPrice(PriceUtil.calcPrice(ourRateplanPrices, dailyInfo.getPrice()));
            }
            return XmlUtils.toXml(GeneValidateResponse.gene(true, validateRq.getDailyInfos(), "1"));
        }
        for (HtDailyRoom htDailyRoom : dailyRooms) {
            htDailyRoom.setSaleNum(0);
            htDailyRoom.setStatus(0);
            log.warn("校验失败，更新库存为零：rp{}，时间：{}，{}", strings[0], validateRq.getCheckIn(), validateRq.getCheckOut());
        }
        this.cacheAndPush(dailyRooms, validateRq.getCheckIn(), validateRq.getCheckOut(), strings[0], -2);
        return XmlUtils.toXml(GeneValidateResponse.gene(false, null, "-1"));
    }

    /**
     * 价格和佣金的比较
     *
     * @param htDailyRooms List<HtDailyRoom>
     * @param dailyRooms   List<HtDailyRoom>
     * @return int
     */
    private int isUpdate(List<HtDailyRoom> htDailyRooms, List<HtDailyRoom> dailyRooms) {
        boolean sub = true;
        for (HtDailyRoom htDailyRoom : htDailyRooms) {
            for (HtDailyRoom dailyRoom : dailyRooms) {
                if (htDailyRoom.getDate().equals(dailyRoom.getDate())) {
                    if (!htDailyRoom.getPrice().equals(dailyRoom.getPrice())) {
                        return 2;
                    }
                    if (!htDailyRoom.getSubPrice().equals(dailyRoom.getSubPrice())) {
                        sub = false;
                    }
                    break;
                }
            }
        }
        if (!sub) {
            return 1;
        }
        return 0;
    }

    /**
     * 异步 更新缓存 更新店铺
     *
     * @param htDailyRoomList List<HtDailyRoom>
     * @param rpCode          String
     * @param flag            int
     */
    @Async
    void cacheAndPush(List<HtDailyRoom> htDailyRoomList, String checkIn, String checkOut, String rpCode, int flag) {
        if (htDailyRoomList.isEmpty()) {
            return;
        }
        // 更新缓存
        redisUtil.saveOrUpdateBatchRates(htDailyRoomList);
        if (flag != 2) {
            log.info("{}，佣金变更更新缓存", rpCode);
            return;
        }
        log.info("{}，价格或库存改变更新缓存或店铺", rpCode);
        // 放入队列进行店铺更新
        Map<String, Object> map = (Map<String, Object>) redisUtil.hashGet(Constant.Redis.RP_BL_STORE.getValue(), rpCode);
        List<HtDailyRoom> htDailyRooms = redisUtil.getRatesBatch(DateUtils.getBetweenDays(checkIn, checkOut), rpCode);
        List<Integer> storeIds = (List<Integer>) map.get("storeIds");
        if (Objects.isNull(storeIds)) {
            return;
        }
        for (Integer storeId : storeIds) {
            PushRatesBody pushRatesBody = new PushRatesBody();
            pushRatesBody.setHtDailyRooms(htDailyRooms);
            pushRatesBody.setRpCode(Long.valueOf(rpCode));
            pushRatesBody.setStoreId(storeId);
            sendMsg.execute(Constant.RabbitMq.RATES, storeId, pushRatesBody);
        }
    }

    /**
     * 预定
     *
     * @param xml String
     * @return String
     */
    @Override
    public String book(String xml, Integer dtId, Integer storeId) {
        BookRq bookRq = XmlUtils.fromXml(xml, BookRq.class);
        BookRqResult bookRqResult = new BookRqResult();
        if (Objects.isNull(bookRq)) {
            bookRqResult.setMessage("请求报文解析错误");
            bookRqResult.setResultCode("-102");
            log.warn("ali预定报文解析错误：{}", xml);
            return XmlUtils.toXml(bookRqResult);
        }
        String ratePlanCode = bookRq.getRatePlanCode();
        String hotelId = bookRq.getHotelId();
        String username = bookRq.getAuthenticationToken().getUsername();
        String rpCode = ratePlanCode.substring(0, ratePlanCode.indexOf("qls"));
        bookRq.setRatePlanCode(rpCode);
        // 默认订单为人工订单
        Integer orderType = OrderConstant.OrdType.Manu.getValue();
        // 默认未支付
        Integer paidType = OrderConstant.AliLocalOrderStatus.Unpaid.getValue();
        Integer isDirect = opGroupService.getIsDirectByHotelCodeAndUsername(username, Long.valueOf(hotelId));
        // 判断是否直连订单
        if (isDirect.equals(0)) {
            log.info("人工订单，店铺：{}，酒店：{}，RP：{}", username, hotelId, rpCode);
        } else {
            orderType = OrderConstant.OrdType.Auto.getValue();
            log.info("直连订单，店铺：{}，酒店：{}，RP：{}", username, hotelId, rpCode);
        }
        // 判断订单是否支付
        Integer payment = bookRq.getPaidPrice();
        if (payment.equals(0)) {
            log.info("订单未支付，店铺：{}，酒店：{}，RP：{}", username, hotelId, rpCode);
        } else {
            paidType = OrderConstant.AliLocalOrderStatus.Paid.getValue();
            log.info("订单已支付，店铺：{}，酒店：{}，RP：{}", username, hotelId, rpCode);
        }
        // todo 只保存订单到数据库
        OrderEntity orderEntity = this.sqlSaveOrder(bookRq, OrderConstant.Channel.Mt.getValue(), orderType, paidType, dtId, storeId);
        if (OrderConstant.AliLocalOrderStatus.Unpaid.getValue().equals(paidType)) {
            bookRqResult.setOrderId(orderEntity.getId().toString());
            bookRqResult.setMessage("创建订单成功");
            bookRqResult.setResultCode("0");
            return XmlUtils.toXml(bookRqResult);
        }
        List<HtDailyRoom> htDailyRooms = redisUtil.getRatesBatch(DateUtils.getBetweenDays(bookRq.getCheckIn(), bookRq.getCheckOut()), rpCode);
        if (htDailyRooms.isEmpty()) {
            bookRqResult.setMessage("其他");
            bookRqResult.setResultCode("-102");
            log.warn("店铺：{}，酒店：{}，RP：{}，ali预定缓存查询价态为空", bookRq.getAuthenticationToken().getUsername(), bookRq.getHotelId(), rpCode);
            return XmlUtils.toXml(bookRqResult);
        }
        List<DailyInfo> dailyInfos = new ArrayList<>();
        for (HtDailyRoom dailyroomEntity : htDailyRooms) {
            String date = dailyroomEntity.getDate();
            Integer price = dailyroomEntity.getPrice();
            DailyInfo dailyInfo = new DailyInfo();
            dailyInfo.setDay(date);
            dailyInfo.setPrice(price);
            dailyInfo.setSubPrice(dailyroomEntity.getSubPrice());
            dailyInfos.add(dailyInfo);
        }
        bookRq.setDailyInfos(dailyInfos);
        // todo 渠道下单
        R r = mtRemoteService.book(bookRq);
        int code = r.getCode();
        if (code != 0) {
            bookRqResult.setMessage("其他");
            bookRqResult.setResultCode("-100");
            log.warn("店铺：{}，酒店：{}，RP：{}，下单失败", bookRq.getAuthenticationToken().getUsername(), bookRq.getHotelId(), rpCode);
            return XmlUtils.toXml(bookRqResult);
        }
        // 更新购买渠道的订单号
        orderEntity.setPayPrice(payment);
        orderEntity.setBuyOrderId(r.get("buyOrderId").toString());
        orderService.updateById(orderEntity);
        // 返回飞猪使用数据库id当作订单号
        bookRqResult.setOrderId(orderEntity.getId().toString());
        bookRqResult.setMessage("创建订单成功");
        bookRqResult.setResultCode("0");
        return XmlUtils.toXml(bookRqResult);
    }

    /**
     * 数据库保存订单
     *
     * @param bookRq    BookRq
     * @param buySource Integer
     * @param orderType Integer
     * @param dtId      Integer
     * @param storeId   Integer
     * @return OrderEntity
     */
    private OrderEntity sqlSaveOrder(BookRq bookRq, Integer buySource, Integer orderType, Integer paidType, Integer dtId, Integer storeId) {
        OrderEntity orderEntity = new OrderEntity();
        orderEntity.setDtId(dtId);
        orderEntity.setDtStoreId(storeId);
        orderEntity.setBuySource(buySource);
        orderEntity.setOrderType(orderType);
        orderEntity.setBuyStatus(OrderConstant.MtLocalOrdBuyStatus.Unpurchased.getValue());
        orderEntity.setOrderStatus(paidType);
        orderEntity.setDate(new Date());
        orderEntity.setOrderCode(Long.valueOf(bookRq.getTaoBaoOrderId()));
        orderEntity.setShid(Long.valueOf(bookRq.getTaoBaoHotelId()));
        orderEntity.setHotelCode(Long.valueOf(bookRq.getHotelId()));
        orderEntity.setSrc(Long.valueOf(bookRq.getTaoBaoRoomTypeId()));
        orderEntity.setRoomCode(Long.valueOf(bookRq.getRoomTypeId()));
        orderEntity.setSrpc(Long.valueOf(bookRq.getTaoBaoRatePlanId()));
        orderEntity.setRateplanCode(Long.valueOf(bookRq.getRatePlanCode()));
        orderEntity.setPlantfrom(bookRq.getChannel());
        orderEntity.setPlanformGoodsId(Long.valueOf(bookRq.getTaoBaoGid()));
        orderEntity.setCheckInDate(DateUtils.stringToDate(bookRq.getCheckIn(), "yyyy-MM-dd"));
        orderEntity.setCheckOutDate(DateUtils.stringToDate(bookRq.getCheckOut(), "yyyy-MM-dd"));
        orderEntity.setEarliestTime(DateUtils.stringToDate(bookRq.getEarliestArriveTime(), "yyyy-MM-dd HH:mm:ss"));
        orderEntity.setLatestTime(DateUtils.stringToDate(bookRq.getLatestArriveTime(), "yyyy-MM-dd HH:mm:ss"));
        orderEntity.setRoomNum(bookRq.getRoomNum());
        orderEntity.setPerNum(Integer.valueOf(bookRq.getOccupancy()));
        orderEntity.setPriceType(Integer.valueOf(bookRq.getPriceType()));
        orderEntity.setInventoryType(Integer.valueOf(bookRq.getInventoryType()));
        orderEntity.setTotalPrice(bookRq.getTotalPrice());
        orderEntity.setOtherFees(bookRq.getOtherFee());
        orderEntity.setPayPrice(bookRq.getPaidPrice());
        orderEntity.setReducedPrice(Integer.valueOf(bookRq.getTotalSellerPromotion()));
        orderEntity.setPaymentType(Integer.valueOf(bookRq.getPaymentType()));
        orderEntity.setName(bookRq.getContactName());
        orderEntity.setPhone(bookRq.getContactTel());
        orderEntity.setEmail(bookRq.getContactEmail());
        orderEntity.setNote(bookRq.getComment());
        orderEntity.setZfbId(bookRq.getAlipayTradeNo());
        orderEntity.setPaymentType(Integer.valueOf(bookRq.getOriginPaymentType()));
        orderService.save(orderEntity);
        List<DailyInfoEntity> dailyInfoEntities = Lists.newArrayList();
        List<DailyOriInfoEntity> dailyOriInfoEntities = Lists.newArrayList();
        List<DailyDisInfoEntity> dailyDisInfoEntities = Lists.newArrayList();
        List<GuestEntity> guestEntities = Lists.newArrayList();
        if (Objects.nonNull(bookRq.getDailyInfos())) {
            for (DailyInfo dailyInfo : bookRq.getDailyInfos()) {
                DailyInfoEntity dailyroomEntity = new DailyInfoEntity();
                dailyroomEntity.setOrderCode(orderEntity.getOrderCode());
                dailyroomEntity.setDate(DateUtils.stringToDate(dailyInfo.getDay(), "yyyy-MM-dd"));
                dailyroomEntity.setPrice(Long.valueOf(dailyInfo.getPrice()));
                dailyroomEntity.setBreakfastNum(dailyInfo.getBreakFast());
                dailyInfoEntities.add(dailyroomEntity);
            }
            dailyInfoService.saveBatch(dailyInfoEntities);
        }
        if (Objects.nonNull(bookRq.getSignMemberDailyInfos())) {
            for (DailyInfo dailyInfo : bookRq.getSignMemberDailyInfos()) {
                DailyOriInfoEntity dailyOriInfoEntity = new DailyOriInfoEntity();
                dailyOriInfoEntity.setOrderCode(orderEntity.getOrderCode());
                dailyOriInfoEntity.setDate(DateUtils.stringToDate(dailyInfo.getDay(), "yyyy-MM-dd"));
                dailyOriInfoEntity.setPrice(Long.valueOf(dailyInfo.getPrice()));
                dailyOriInfoEntity.setBreakfastNum(dailyInfo.getBreakFast());
                dailyOriInfoEntities.add(dailyOriInfoEntity);
            }
            dailyOriInfoService.saveBatch(dailyOriInfoEntities);
        }
        if (Objects.nonNull(bookRq.getDisDailyInfos())) {
            for (DailyInfo dailyInfo : bookRq.getDisDailyInfos()) {
                DailyDisInfoEntity dailyDisInfoEntity = new DailyDisInfoEntity();
                dailyDisInfoEntity.setOrderCode(orderEntity.getOrderCode());
                dailyDisInfoEntity.setDate(DateUtils.stringToDate(dailyInfo.getDay(), "yyyy-MM-dd"));
                dailyDisInfoEntity.setPrice(Long.valueOf(dailyInfo.getPrice()));
                dailyDisInfoEntity.setBreakfastNum(dailyInfo.getBreakFast());
                dailyDisInfoEntities.add(dailyDisInfoEntity);
            }
            dailyDisInfoService.saveBatch(dailyDisInfoEntities);
        }
        if (Objects.nonNull(bookRq.getOrderGuests())) {
            for (OrderGuest guest : bookRq.getOrderGuests()) {
                GuestEntity guestEntity = new GuestEntity();
                guestEntity.setOrderCode(orderEntity.getOrderCode());
                guestEntity.setName(guest.getName());
                guestEntity.setRoomPos(Integer.valueOf(guest.getRoomPos()));
                guestEntity.setIdType(guest.getIdType());
                guestEntity.setIdCode(guest.getIdCode());
                guestEntities.add(guestEntity);
            }
            guestService.saveBatch(guestEntities);
        }
        return orderEntity;
    }

    @Override
    public String paySuccess(String xml, String username) {
        PaySuccess paySuccess = XmlUtils.fromXml(xml, PaySuccess.class);
        PaySuccessResult paySuccessResult = new PaySuccessResult();
        if (Objects.isNull(paySuccess)) {
            log.warn("店铺：{}，付款时报文解析失败", username);
            paySuccessResult.setResultCode("-400");
            paySuccessResult.setMessage("报文解析异常");
            return XmlUtils.toXml(paySuccessResult);
        }
        OrderEntity orderEntity = orderService.getById(paySuccess.getOrderId());
        Integer payPrice = orderEntity.getPayPrice();
        // 如果有价格说明已支付（已经从下单渠道下单）
        if (!payPrice.equals(0)) {
            paySuccessResult.setResultCode("0");
            paySuccessResult.setMessage("成功");
            return XmlUtils.toXml(paySuccessResult);
        }
        orderEntity.setOrderStatus(OrderConstant.AliLocalOrderStatus.Paid.getValue());
        orderEntity.setZfbId(paySuccess.getAlipayTradeNo());
        int amount = 0;
        int sub = 0;
        String checkIn = DateUtils.format(orderEntity.getCheckInDate());
        String checkOut = DateUtils.format(orderEntity.getCheckOutDate());
        List<HtDailyRoom> htDailyRooms = redisUtil.getRatesBatch(DateUtils.getBetweenDays(checkIn, checkOut), orderEntity.getRateplanCode().toString());
        if (Objects.isNull(htDailyRooms)) {
            log.warn("店铺：{}，订单号：{}，订单付款时查询缓存价格失败", username, paySuccess.getTaoBaoOrderId());
            paySuccessResult.setResultCode("-400");
            paySuccessResult.setMessage("未查询到价格缓存");
            return XmlUtils.toXml(paySuccessResult);
        }
        for (HtDailyRoom htDailyRoom : htDailyRooms) {
            amount += htDailyRoom.getPrice();
            sub += htDailyRoom.getSubPrice();
        }
        Integer roomNum = orderEntity.getRoomNum();
        int payment = (amount - sub) * roomNum;
        orderEntity.setPayPrice(paySuccess.getPayment());
        orderEntity.setBuyOrderPrice(payment);
        orderService.updateById(orderEntity);
        Integer isDirect = opGroupService.getIsDirectByHotelCodeAndUsername(username, orderEntity.getHotelCode());
        if (isDirect.equals(0)) {
            paySuccessResult.setResultCode("0");
            paySuccessResult.setMessage("成功");
            return XmlUtils.toXml(paySuccessResult);
        }
//        // todo 计算出实际利润 大于0 直接下单 小于零如果是直连订单转人工
//        double fzCommission = 0.92;
//        if(paySuccess.getPayment() * fzCommission - payment < 0) {
//            orderEntity.setOrderType(OrderConstant.OrdType.Manu.getValue());
//            orderService.updateById(orderEntity);
//            paySuccessResult.setResultCode("0");
//            paySuccessResult.setMessage("成功");
//            return XmlUtils.toXml(paySuccessResult);
//        }
        BookRq bookRq = this.transForm(orderEntity, htDailyRooms, username);
        R r = mtRemoteService.book(bookRq);
        int code = r.getCode();
        if (code == 0) {
            orderEntity.setBuyOrderId(r.get("buyOrderId").toString());
            orderEntity.setBuyStatus(OrderConstant.MtLocalOrdBuyStatus.Purchasing.getValue());
            orderService.updateById(orderEntity);
            paySuccessResult.setResultCode("0");
            paySuccessResult.setMessage("成功");
            return XmlUtils.toXml(paySuccessResult);
        }
        orderEntity.setBuyStatus(OrderConstant.MtLocalOrdBuyStatus.Purchfailure.getValue());
        orderService.updateById(orderEntity);
        paySuccessResult.setResultCode("支付失败");
        paySuccessResult.setMessage((String) r.get("message"));
        return XmlUtils.toXml(paySuccessResult);
    }

    /**
     * 查询订单状态
     *
     * @param xml String
     * @return String
     */
    @Override
    public String queryStatus(String xml) {
        QueryStatusRqResult queryStatusRqResult = new QueryStatusRqResult();
        QueryStatusRqRequest queryStatusRqRequest = XmlUtils.fromXml(xml, QueryStatusRqRequest.class);
        if (Objects.isNull(queryStatusRqRequest)) {
            log.warn("查询订单报文解析异常");
            queryStatusRqResult.setMessage("报文解析异常");
            queryStatusRqResult.setResultCode("-301");
            return XmlUtils.toXml(queryStatusRqResult);
        }
        String orderCode = queryStatusRqRequest.getTaoBaoOrderId();
        OrderEntity orderEntity = orderService.sqlSelectByOrderCode(Long.valueOf(orderCode));
        // 未付款的订单不在库中 查询会失败（假数据返回）
        if (orderEntity == null) {
            queryStatusRqResult.setMessage("处理成功");
            queryStatusRqResult.setResultCode("0");
            queryStatusRqResult.setStatus("-302");
            queryStatusRqResult.setOrderId(queryStatusRqRequest.getOrderId());
            return XmlUtils.toXml(queryStatusRqResult);
        }
        queryStatusRqResult.setMessage("处理成功");
        queryStatusRqResult.setResultCode("0");
        queryStatusRqResult.setTaoBaoOrderId(orderCode);
        queryStatusRqResult.setOrderId(orderEntity.getId().toString());
        OrderConstant.MtLocalOrdBuyStatus mtLocalOrdBuyStatus = OrderConstant.MtLocalOrdBuyStatus.getLocalOrdBuyStatusByValue(orderEntity.getBuyStatus());
        switch (mtLocalOrdBuyStatus) {
            case Purchased:
                if (orderEntity.getOtherFees() != null) {
                    queryStatusRqResult.setOtherFee(orderEntity.getOtherFees().toString());
                } else {
                    queryStatusRqResult.setOtherFee("0");
                }
                queryStatusRqResult.setTotalRoomPrice(orderEntity.getBuyOrderPrice().toString());
                queryStatusRqResult.setStatus(OrderConstant.AliQueryStatus.Confirm.getValue().toString());
                break;
            // 采购失败
            case Purchfailure:
                queryStatusRqResult.setStatus(OrderConstant.AliQueryStatus.UnConfirm.getValue().toString());
                break;
            // 已取消
            case Canceled:
                queryStatusRqResult.setStatus(OrderConstant.AliQueryStatus.Canceled.getValue().toString());
                break;
            // 已入住
            case CheckIn:
                queryStatusRqResult.setStatus(OrderConstant.AliQueryStatus.CheckIn.getValue().toString());
                break;
            // 未采购
            // 已受理
            // 采购中
            // 退款中
            // 已退款
            // 退款失败
            // 订单取消中
            // 取消失败
            // 已采购
            default:
                queryStatusRqResult.setStatus(OrderConstant.AliQueryStatus.Dealing.getValue().toString());
                break;
        }
        return XmlUtils.toXml(queryStatusRqResult);
    }

    /**
     * 申请退款通知
     *
     * @param xml String
     * @return String
     */
    @Override
    public String orderRefund(String xml) {
        OrderRefundRq orderRefundRq = XmlUtils.fromXml(xml, OrderRefundRq.class);
        CancelRqResult cancelRqResult = new CancelRqResult();
        if (Objects.isNull(orderRefundRq)) {
            cancelRqResult.setMessage("报文解析异常");
            cancelRqResult.setResultCode("-200");
            return XmlUtils.toXml(cancelRqResult);
        }
        String orderCode = orderRefundRq.getTaoBaoOrderId();
        if (StringUtils.isBlank(orderCode)) {
            cancelRqResult.setMessage("不存在此订单");
            cancelRqResult.setResultCode("-204");
            return XmlUtils.toXml(cancelRqResult);
        }
        OrderEntity orderEntity = orderService.sqlSelectByOrderCode(Long.valueOf(orderCode));
        //查不到数据返回成功
        if (Objects.isNull(orderEntity)) {
            cancelRqResult.setMessage("不存在此订单");
            cancelRqResult.setResultCode("-204");
            return XmlUtils.toXml(cancelRqResult);
        }
        // 申请退款只是通知 不需要其他操作 支付更改数据库状态
        cancelRqResult.setOrderId(orderEntity.getId().toString());
        cancelRqResult.setResultCode("0");
        orderEntity.setOrderStatus(OrderConstant.AliLocalOrderStatus.ApplyRefund.getValue());
        orderService.updateById(orderEntity);
        return XmlUtils.toXml(cancelRqResult);
    }

    /**
     * 取消订单
     *
     * @param xml String
     * @return String
     */
    @Override
    public String cancel(String xml) {
        CancelRq cancelRq = XmlUtils.fromXml(xml, CancelRq.class);
        CancelRqResult cancelRqResult = new CancelRqResult();
        if (Objects.isNull(cancelRq)) {
            cancelRqResult.setMessage("取消订单-报文解析异常");
            cancelRqResult.setResultCode("-200");
            return XmlUtils.toXml(cancelRqResult);
        }
        OrderEntity orderEntity = orderService.getById(cancelRq.getOrderId());
        //查不到数据为空则返回成功
        if (Objects.isNull(orderEntity)) {
            cancelRqResult.setMessage("不存在此订单");
            cancelRqResult.setResultCode("-204");
            return XmlUtils.toXml(cancelRqResult);
        }
        // 未购买订单直接取消成功
        String buyOrderId = orderEntity.getBuyOrderId();
        if(Objects.isNull(buyOrderId)) {
            cancelRqResult.setOrderId(cancelRq.getOrderId().toString());
            cancelRqResult.setMessage("取消成功");
            cancelRqResult.setResultCode("0");
            return XmlUtils.toXml(cancelRqResult);
        }
        // 申请取消订单
        cancelRq.setBuyOrderCode(orderEntity.getBuyOrderId());
        orderEntity.setOrderStatus(OrderConstant.AliLocalOrderStatus.Calcel.getValue());
        R r = mtRemoteService.cancel(cancelRq);
        if (r.getCode() == 0) {
            // 已取消
            orderEntity.setBuyStatus(OrderConstant.MtLocalOrdBuyStatus.Canceled.getValue());
            orderService.updateById(orderEntity);
            cancelRqResult.setOrderId(cancelRq.getOrderId().toString());
            cancelRqResult.setMessage("取消成功");
            cancelRqResult.setResultCode("0");
            log.info("店铺：{}，订单号：{}，取消订单成功",
                    cancelRq.getAuthenticationToken().getUsername(), orderEntity.getOrderCode());
            return XmlUtils.toXml(cancelRqResult);
        } else if (r.getCode() == 1) {
            // 订单取消中
            orderEntity.setBuyStatus(OrderConstant.MtLocalOrdBuyStatus.Canceling.getValue());
            cancelRqResult.setOrderId(cancelRq.getOrderId().toString());
            cancelRqResult.setMessage("订单取消中");
            cancelRqResult.setResultCode("0");
            log.info("店铺：{}，订单号：{}，订单取消中",
                    cancelRq.getAuthenticationToken().getUsername(), orderEntity.getOrderCode());
            return XmlUtils.toXml(cancelRqResult);
        }
        // 订单取消失败
        orderEntity.setBuyStatus(OrderConstant.MtLocalOrdBuyStatus.CancelFail.getValue());
        orderService.updateById(orderEntity);
        cancelRqResult.setMessage("取消失败，请联系客服进行取消");
        cancelRqResult.setResultCode("-200");
        cancelRqResult.setMessage((String) r.get("message"));
        return XmlUtils.toXml(cancelRqResult);
    }

    @Override
    public R manuBook(Integer orderId) {
        OrderEntity orderEntity = orderService.getById(orderId);
        DtStore dtStore = dtStoreService.getById(orderEntity.getDtStoreId());
        List<HtDailyRoom> htDailyRooms = redisUtil.getRatesBatch(DateUtils.getBetweenDays(DateUtils.format(orderEntity.getCheckInDate()), DateUtils.format(orderEntity.getCheckOutDate())), orderEntity.getRateplanCode().toString());
        BookRq bookRq = this.transForm(orderEntity, htDailyRooms, dtStore.getName());
        R r = mtRemoteService.book(bookRq);
        int code = r.getCode();
        if (code != 0) {
            log.warn("人工订单，支付失败，酒店：{}，rp:{}，订单号：{}", orderEntity.getHotelCode(), orderEntity.getRateplanCode(), orderEntity.getOrderCode());
            orderEntity.setBuyStatus(OrderConstant.MtLocalOrdBuyStatus.Purchfailure.getValue());
            orderService.updateById(orderEntity);
            return R.error("下单失败");
        }
        orderEntity.setBuyOrderId(r.get("buyOrderId").toString());
        log.warn("人工订单，支付成功，酒店：{}，rp:{}，订单号：{}", orderEntity.getHotelCode(), orderEntity.getRateplanCode(), orderEntity.getOrderCode());
        orderEntity.setBuyStatus(OrderConstant.MtLocalOrdBuyStatus.Purchasing.getValue());
        orderService.updateById(orderEntity);
        return R.ok("下单成功");
    }

    /**
     * 订单转换成 BookRq
     *
     * @param orderEntity OrderEntity
     * @return BookRq
     */
    private BookRq transForm(OrderEntity orderEntity, List<HtDailyRoom> htDailyRooms, String username) {
        List<DailyInfo> dailyInfos = new ArrayList<>();
        for (HtDailyRoom htDailyRoom : htDailyRooms) {
            DailyInfo dailyInfo = new DailyInfo();
            dailyInfo.setPrice(htDailyRoom.getPrice());
            dailyInfo.setSubPrice(htDailyRoom.getSubPrice());
            dailyInfo.setDay(htDailyRoom.getDate());
            dailyInfos.add(dailyInfo);
        }
        BookRq bookRq = new BookRq();
        bookRq.setDailyInfos(dailyInfos);
        bookRq.setHotelId(orderEntity.getHotelCode().toString());
        bookRq.setTaoBaoOrderId(orderEntity.getOrderCode().toString());
        bookRq.setCheckIn(DateUtils.format(orderEntity.getCheckInDate()));
        bookRq.setCheckOut(DateUtils.format(orderEntity.getCheckOutDate()));
        bookRq.setRoomNum(orderEntity.getRoomNum());
        bookRq.setContactTel(orderEntity.getPhone());
        bookRq.setRatePlanCode(orderEntity.getRateplanCode().toString());
        bookRq.setLatestArriveTime(DateUtils.format(orderEntity.getLatestTime(), DateUtils.DATE_TIME_PATTERN));
        AuthenticationToken authenticationToken = new AuthenticationToken();
        authenticationToken.setUsername(username);
        bookRq.setAuthenticationToken(authenticationToken);
        // 入住人
        Map<String, Object> map = new HashMap<>();
        map.put("order_code", orderEntity.getOrderCode());
        List<GuestEntity> guestEntities = guestService.listByMap(map);
        List<OrderGuest> orderGuests = new ArrayList<>();
        for (GuestEntity guestEntity : guestEntities) {
            OrderGuest orderGuest = new OrderGuest();
            orderGuest.setName(guestEntity.getName());
            orderGuests.add(orderGuest);
        }
        bookRq.setOrderGuests(orderGuests);
        bookRq.setContactName(orderEntity.getName());
        return bookRq;
    }

}
